﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.Objects;
using System.Linq;
using System.Text;

namespace EBA.Data
{
    public abstract class ObjectContextUnitOfWork<TObjectContext>:IUnitOfWork where TObjectContext : ObjectContext
    {
        protected abstract ObjectContext ObjectContext
        {
            get;
        }

        protected virtual DbTransaction DbTransaction {get;set;}

        public virtual void BeginTransaction()
        {
            if (this.ObjectContext.Connection.State != System.Data.ConnectionState.Open)
            {
                this.ObjectContext.Connection.Open();
            }

            this.DbTransaction = this.ObjectContext.Connection.BeginTransaction();
        }

        public virtual void CommitTransaction()
        {
            if (this.DbTransaction == null)
            {
                throw new InvalidOperationException("The transaction has not been begined");
            }
            else
            {
                this.DbTransaction.Commit();
                this.OnSubmittedChanges();
            }

            this.DbTransaction = null;
        }

        public virtual void EndTransaction()
        {
            if (this.DbTransaction != null)
            {
                this.DbTransaction.Dispose();
                this.DbTransaction = null;
            }
        }

        public virtual void RollbackTransaction()
        {
            if (this.DbTransaction == null)
            {
                throw new InvalidOperationException("The transaction has not been begined");
            }
            else
            {
                if (this.DbTransaction.Connection != null)
                {
                    this.DbTransaction.Rollback();
                }
            }
            this.DbTransaction = null;
        }

        public virtual void SubmitChanges()
        {
            try
            {
                this.ObjectContext.SaveChanges();
                if (this.DbTransaction == null)
                {
                    this.OnSubmittedChanges();
                }
            }
            catch (OptimisticConcurrencyException ex)
            {
                throw new DBConcurrencyException("", ex);
            }

        }

        void OnSubmittedChanges()
        {
            if (this.SubmittedChanges != null)
            {
                this.SubmittedChanges(this, EventArgs.Empty);
            }
        }

        public event EventHandler SubmittedChanges;
    }
}
